﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace LaughingDog
{
    /// <summary>
    /// Class to be used for generating random data.
    /// </summary>
    public static class Random
    {
        private static Int32 mSeed = (Int32)DateTime.Now.Ticks;

        private static System.Random mRandom = new System.Random(mSeed);
        
        /// <summary>
        /// Sets or gets the seed for the random value generator.
        /// </summary>
        public static Int32 Seed { get { return mSeed; } set { mSeed = value; createRandomGenerator(); } }

        private static void createRandomGenerator()
        {
            mRandom = new System.Random(mSeed);
        }

        /// <summary>
        /// Returns a random nonnegative random Int32.
        /// </summary>
        /// <returns>The random Int32.</returns>
        public static Int32 Int32()
        {
            return mRandom.Next();
        }

        /// <summary>
        /// Returns a random nonnegative random Int32.
        /// </summary>
        /// <param name="maxValue">The maximum value of the Int32.</param>
        /// <returns>The random Int32.</returns>
        public static Int32 Int32(Int32 maxValue)
        {
            return Int32(0, maxValue);
        }

        /// <summary>
        /// Returns a random nonnegative random Int32.
        /// </summary>
        /// <param name="minValue">The minimum value of the Int32.</param>
        /// <param name="maxValue">The maximum value of the Int32.</param>
        /// <returns>The random Int32.</returns>
        public static Int32 Int32(Int32 minValue, Int32 maxValue)
        {
            return mRandom.Next(minValue, maxValue);
        }

        /// <summary>
        /// Returns a random Single.
        /// </summary>
        /// <returns>The random Single.</returns>
        public static Single Single()
        {
            return Single(System.Single.MaxValue);
        }

        /// <summary>
        /// Returns a random Single.
        /// </summary>
        /// <param name="maxValue">The maximum value of the Single.</param>
        /// <returns>The random Single.</returns>
        public static Single Single(Single maxValue)
        {
            return Single(0, maxValue);
        }

        /// <summary>
        /// Returns a random Single.
        /// </summary>
        /// <param name="minValue">The minimum value of the Single.</param>
        /// <param name="maxValue">The maximum value of the Single.</param>
        /// <returns>The random Single.</returns>
        public static Single Single(Single minValue, Single maxValue)
        {
            return (Single)(maxValue - minValue) * (Single)mRandom.NextDouble() + minValue;
        }

        /// <summary>
        /// Returns a random Double between 0.0 and 1.0.
        /// </summary>
        /// <returns>The random Double.</returns>
        public static Double Double()
        {
            return mRandom.NextDouble();
        }

        /// <summary>
        /// Returns a random Double.
        /// </summary>
        /// <param name="maxValue">The maximum value of the Double.</param>
        /// <returns>The random Double.</returns>
        public static Double Double(Double maxValue)
        {
            return Double(0, maxValue);
        }

        /// <summary>
        /// Returns a random Double.
        /// </summary>
        /// <param name="minValue">The minimum value of the Double.</param>
        /// <param name="maxValue">The maximum value of the Double.</param>
        /// <returns>The random Double.</returns>
        public static Double Double(Double minValue, Double maxValue)
        {
            return (maxValue - minValue) * mRandom.NextDouble() + minValue;
        }

        /// <summary>
        /// Returns a random Boolean.
        /// </summary>
        /// <returns>The random Boolean.</returns>
        public static Boolean Boolean()
        {
            return Double() > 0.5d;
        }

        /// <summary>
        /// Returns a random Vector2.
        /// </summary>
        /// <returns>The random Vector2.</returns>
        public static Vector2 Vector2()
        {
            return new Vector2(Single(), Single());
        }

        /// <summary>
        /// Returns a random Vector2.
        /// </summary>
        /// <param name="minValues">The minimum values of the Vector2.</param>
        /// <param name="maxValues">The maximum values of the Vector2.</param>
        /// <returns>The random Vector2.</returns>
        public static Vector2 Vector2(Single minValues, Single maxValues)
        {
            return Vector2(new Vector2(minValues, maxValues), new Vector2(minValues, maxValues));
        }

        /// <summary>
        /// Returns a random Vector2.
        /// </summary>
        /// <param name="xValues">The minimum and maximum values of X.</param>
        /// <param name="yValues">The minimum and maximum values of Y.</param>
        public static Vector2 Vector2(Vector2 xValues, Vector2 yValues)
        {
            return new Vector2(Single(xValues.X, xValues.Y), Single(yValues.X, yValues.Y));
        }

        /// <summary>
        /// Returns a random Colour.
        /// </summary>
        /// <returns>The random Colour.</returns>
        public static Color Colour()
        {
            return new Color(Single(0, 1), Single(0, 1), Single(0, 1), Single(0, 1));
        }

        /// <summary>
        /// Returns a random object from a list of objects.
        /// </summary>
        /// <typeparam name="T">The type of object.</typeparam>
        /// <param name="items">The list of objects.</param>
        /// <returns>The random object.</returns>
        public static T Item<T>(List<T> items)
        {
            return items[Int32(items.Count)];
        }
    }
}
